﻿package  {
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import ShapeModel;
	
	public class ObjectDraw extends Sprite {

		private var spDisplayObject:Sprite; // this is the 2D object that is drawn to the screen
		private var shapeModel:ShapeModel;
		
		private var displayVertices:Vector.<Point>;
		private var vertexScale:Array = [];
		
		private var faceMag:Array = [];
		
		private var menuItemHandler:MenuItemHandler;
		
		private var lineColour:uint;
		private var lineAlpha:Number;
		private var faceAlpha:Number;
		private var faceColours:Vector.<uint>;
		
		private var max:Number;
		private var min:Number;
		
		// constructor
		public function ObjectDraw(parentSpriteBoard:Sprite,
								   objectRotate:ObjectRotate, 
								   shapeModel:ShapeModel,
								   menuItemHandler:MenuItemHandler
								   ) 
		{
			max = 0;
			min = 0;
			
			this.menuItemHandler = menuItemHandler;
			
			this.shapeModel = shapeModel;
			
			faceColours = new Vector.<uint>;
			
			spDisplayObject = new Sprite();
			parentSpriteBoard.addChild(spDisplayObject);
			
			displayVertices = new Vector.<Point>();
			setDrawProperties();

		}
		
		public function clearObjectDisplay() {
			spDisplayObject.graphics.clear();
		}
		
		/** 
			the drawing function for the object (shape plus links)
		*/
		
		public function drawObject():void {
			
			
			applyRotations();
			
			var faces:Vector.<Array> = shapeModel.getFaces();
			var i:int;
			var j:int;
			
			// ****** this needs some modification and logic to accomodate for the clickable links.
			
			
			for (i = 0; i < shapeModel.getNumFaces(); i++) {
				var currentFace:int = faceMag[i][1];
				var faceLength:int = faces[currentFace].length;
				spDisplayObject.graphics.lineStyle(1, lineColour,lineAlpha);
				
				spDisplayObject.graphics.beginFill(faceColours[currentFace], faceAlpha);
				spDisplayObject.graphics.moveTo(displayVertices[faces[currentFace][0]].x, displayVertices[faces[currentFace][0]].y);
				
				// join the dots
				for (j = 1; j < faceLength; j++) {
					spDisplayObject.graphics.lineTo(displayVertices[faces[currentFace][j]].x,displayVertices[faces[currentFace][j]].y);
				}
				
				// link up to starting point
				spDisplayObject.graphics.lineTo(displayVertices[faces[currentFace][0]].x,displayVertices[faces[currentFace][0]].y);
				spDisplayObject.graphics.endFill();
			}
			//
			
			for (j = 0; j < shapeModel.getNumVertices(); j++) {
				menuItemHandler.setPosition(j, displayVertices[j], vertexScale[j][0]);
			}
			
		}
		
		
		/**
			Apply the rotations performed by the ObjectRotate class
		*/
		private function applyRotations():void {
			
			// some of these variables can be made public...
			var vertices:Vector.<Vector3D> = shapeModel.getRotatedVertices();
			var faces:Vector.<Array> = shapeModel.getFaces();
			
			var zAverage:Number;
			var distance:Number;
			var currentFace:int;
			var faceLength:int;
			
			var i:int;
			
			// face depth sorting...
			for (i = 0; i < shapeModel.getNumFaces(); i++) {
				faceLength = faces[i].length; // slightly misleading... faceLength is the number of vertices for each face.
				zAverage = 0;
				
				// find the midpoint delimited by the faces vertices
				for (var j:int = 0; j < faceLength; j++) {
					zAverage +=  vertices[faces[i][j]].z;
				}
				zAverage /=  faceLength;
				
				distance = zAverage;
				faceMag[i] = [distance, i];
			}

			// sort the vertices
			for (i = 0; i < shapeModel.getNumVertices(); i++) {
				
				var scale = (vertices[i].z + 110.5) / 181.7;
				vertexScale[i] = [scale, i];
				
				
			}
			//==
			
			
			
			// painters algorithm
			faceMag.sort(byDistance);
			
			// convert 3D rotated shape vertices to 2D points
			for (i = 0; i < shapeModel.getNumVertices(); i++) {
				displayVertices[i] = new Point();
				displayVertices[i].x = vertices[i].x;
				displayVertices[i].y = vertices[i].y;
			}

		}
		
		private function setDrawProperties():void {
			
			// this will do for now, but will have to write accessor methods if these properties are to be variable
			lineColour = shapeModel.getLineColour();
			lineAlpha = shapeModel.getLineAlpha();
			faceAlpha = shapeModel.getFaceAlpha();
			
			for (var i:int = 0; i < shapeModel.getNumFaces(); i++) {
				faceColours[i] = shapeModel.getFaceColours(i);
			}
		}
		
		/**
			sorting algorithm to determine closest face midpoint
		*/
		private function byDistance(v:Array, w:Array):Number {
			if (v[0] > w[0]) {
				return -1;
			}
			else if (v[0]<w[0]) {
				return 1;
			}
			else {
				return 0;
			}
		}
		
	}
}
